﻿using CommonQuery.Builder;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace EntityFrameworkHelper
{
    /// <summary>
    ///     Interface IRepository
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IRepository<T> where T : class
    {
        /// <summary>
        ///     Adds the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        void Add(T entity);

        /// <summary>
        ///     Adds for batching.
        /// </summary>
        /// <param name="entities">The entities.</param>
        void AddForBatchingNoContext(IEnumerable<T> entities);

        /// <summary>
        ///     Attaches the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        void Attach(T entity);

        /// <summary>
        ///     Attaches for batching asynchronous.
        ///     (注意：生成SQL并启用底层事务机制，但和原始的EF中的Context无关，所以不要在DbContext上下文使用)
        /// </summary>
        /// <param name="predicate">The predicate.</param>
        /// <param name="updateExpression">The update expression.</param>
        /// <returns>Task&lt;System.Boolean&gt;.</returns>
        Task<bool> AttachForBatchingNoContextAsync(Expression<Func<T, bool>> predicate,
            Expression<Func<T, T>> updateExpression);

        /// <summary>
        ///     Attaches for batching asynchronous.
        ///     (注意：生成SQL并启用底层事务机制，但和原始的EF中的Context无关，所以不要在DbContext上下文使用)
        /// </summary>
        /// <param name="qb">The qb.</param>
        /// <param name="updateExpression">The update expression.</param>
        /// <returns>Task&lt;System.Boolean&gt;.</returns>
        Task<bool> AttachForBatchingNoContextAsync(BaseQueryBuilder qb,
            Expression<Func<T, T>> updateExpression);

        /// <summary>
        ///     Attaches for batching with context asynchronous.
        ///     批量更新可用于DbContext上下文
        /// </summary>
        /// <param name="entities">The entities.</param>
        /// <returns>Task&lt;System.Boolean&gt;.</returns>
        void AttachForBatchingWithContextAsync(IList<T> entities);

        /// <summary>
        ///     Deletes the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        void Delete(T entity);

        /// <summary>
        ///     Gets the specified predicate.
        /// </summary>
        /// <param name="predicate">The predicate.</param>
        /// <returns>T.</returns>
        Task<T> GetAsync(Func<T, bool> predicate);

        /// <summary>
        ///     Gets the asynchronous.
        /// </summary>
        /// <param name="queryBuilder">The query builder.</param>
        /// <returns>Task&lt;T&gt;.</returns>
        Task<T> GetAsync(BaseQueryBuilder queryBuilder);

        /// <summary>
        ///     Gets the asynchronous.
        /// </summary>
        /// <typeparam name="KeyType">The type of the key type.</typeparam>
        /// <param name="id">The identifier.</param>
        /// <returns>Task&lt;T&gt;.</returns>
        Task<T> GetAsync<KeyType>(KeyType id);

        /// <summary>
        ///     Gets the list asynchronous.
        /// </summary>
        /// <param name="queryBuilder">The query builder.</param>
        /// <returns>Task&lt;IList&lt;T&gt;&gt;.</returns>
        Task<IList<T>> GetListAsync(BaseQueryBuilder queryBuilder);

        /// <summary>
        ///     Gets all.
        /// </summary>
        /// <param name="predicate">The predicate.</param>
        /// <returns>IEnumerable&lt;T&gt;.</returns>
        Task<IEnumerable<T>> QueryAsync(Func<T, bool> predicate = null);

        /// <summary>
        ///     Queries the asynchronous.
        /// </summary>
        /// <param name="predicate">The predicate.</param>
        /// <returns>Task&lt;IList&lt;T&gt;&gt;.</returns>
        Task<IList<T>> QueryAsync(Expression<Func<T, bool>> predicate);
    }
}